// olorSkin.cpp : Implementation of ColorSkin
#include "stdafx.h"
#include "ColorSkinAddin.h"
#include "olorSkin.h"

static HHOOK g_hNextHook = NULL;
CString ColorSkin::m_szSkinXP;
CString ColorSkin::m_szSkinNeo;

HWND g_hHookDlg = NULL;
CSkinMainWin *g_subModeldlg = NULL;
CSkinMainWin *g_subSkinFrame = NULL; 
/////////////////////////////////////////////////////////////////////////////
// ColorSkin
CList<CSubclassWnd*,CSubclassWnd*> ColorSkin::m_SubWndList;
CSkinButtonResource		ColorSkin::m_btnres;		//skin button resource
CObList ColorSkin::m_hookdlgbtns;
 CMenuBarXP	ColorSkin::m_wndMenuBar;
 CReBarCtrl	ColorSkin::m_wndReBar;


STDMETHODIMP ColorSkin::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IolorSkin
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

HRESULT _stdcall ColorSkin::Uninitialize( LONG lSessionID )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		
	for(int i=0;i<m_SubWndList.GetCount();i++)
	{
		CSubclassWnd*pSubWnd = m_SubWndList.GetAt(m_SubWndList.FindIndex(i));
		delete pSubWnd;
	}
	m_SubWndList.RemoveAll();

	UnhookWindowsHookEx(g_hNextHook);

	return S_OK;
}

HRESULT _stdcall ColorSkin::EndInitialize()
{
	tagAddinManager addInfoManager;
	m_pProjectFramework->get_AddinfoManager(&addInfoManager);
	DWORD threadID = addInfoManager.m_dwMainThreadID;
	
	if(threadID==NULL)
		return S_FALSE;
	
	BOOL bSucceed = ::EnumThreadWindows(threadID,(WNDENUMPROC)EnumSubingWndProc,0);
	
	g_hNextHook = ::SetWindowsHookEx(WH_CALLWNDPROC,HookWndProc,NULL,threadID);
	if(!bSucceed)
		return S_FALSE;

	return S_OK;
	
}

#define     GetWindowStyle(hwnd)    ((DWORD)GetWindowLong(hwnd, GWL_STYLE))

BOOL CALLBACK ColorSkin::EnumChildProc(  HWND hwnd,LPARAM lParam)
{
	CSkinButtonResource *btnres = (CSkinButtonResource *)lParam;
	DWORD style;
	
	CString classname;
	GetClassName( hwnd, classname.GetBufferSetLength(200), 200 );
	classname.ReleaseBuffer();
	style = GetWindowStyle( hwnd );
	if ( classname == "Button" )
	{
		style = (UINT)GetWindowLong(hwnd, GWL_STYLE) & 0xff;
		if ( style == BS_PUSHBUTTON || style == BS_DEFPUSHBUTTON )
		{
			CSkinButton * btn = new CSkinButton();
			m_hookdlgbtns.AddTail(btn);
			CWnd* pWnd = CWnd::FromHandlePermanent(hwnd);
			if ( pWnd == NULL)
			{
				btn->SubclassWindow( hwnd );
				btn->SetResource( &m_btnres );
				return TRUE;
			}

		}
	}
	
	
	return TRUE;
}
LRESULT CALLBACK ColorSkin::HookWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	// alias for message structure
	CWPSTRUCT& cwp = *(CWPSTRUCT*)lParam;

	CString szClassName;
	GetClassName( cwp.hwnd, szClassName.GetBuffer(MAX_PATH), MAX_PATH );
	szClassName.ReleaseBuffer();

	switch(cwp.message)
	{
	case WM_SHOWWINDOW:
		break;
	case WM_CREATE:
		break;
	case WM_INITDIALOG:
		{

			if(szClassName == "#32770" && g_subModeldlg==NULL)
			{
 				m_btnres.LoadSkin(ColorSkin::m_szSkinNeo);
 				::EnumChildWindows(cwp.hwnd,EnumChildProc,(LPARAM)&m_btnres);

				g_subModeldlg = new CSkinMainWin();
				g_subModeldlg ->LoadSkin(ColorSkin::m_szSkinNeo);
				g_subModeldlg ->InstallSkin(cwp.hwnd);
			}

		}
		break;
	case WM_DESTROY:
		{

			if(szClassName == "#32770"&&g_subModeldlg!=NULL)
			{
				delete g_subModeldlg;
				g_subModeldlg = NULL;
				
				POSITION pos;
				pos = m_hookdlgbtns.GetHeadPosition();
				while( pos )
				{
					CObject *ob = m_hookdlgbtns.GetAt(pos);
					if ( ob->GetRuntimeClass() == RUNTIME_CLASS(CSkinButton) )
					{
						delete (CSkinButton*)ob;
					}
					m_hookdlgbtns.GetNext(pos);
				}		
				m_hookdlgbtns.RemoveAll();
			}

			if(szClassName.Find("Afx",0)>=0 && g_subSkinFrame != NULL)
			{
				delete g_subSkinFrame;
				g_subSkinFrame = NULL;
			}
		}
		break;
	}

	return CallNextHookEx(g_hNextHook, nCode, wParam, lParam);
}

BOOL CALLBACK ColorSkin::EnumSubingWndProc( HWND hwnd,LPARAM lParam )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())


	CString szWndClass;
	GetClassName(hwnd,szWndClass.GetBuffer(MAX_PATH),MAX_PATH);
	szWndClass.ReleaseBuffer();
	TRACE("%s\n",szWndClass);
	
	if(szWndClass.Find("Afx:not support now",0)>=0 && g_subSkinFrame == NULL)
	{
//     this line is very odd
		HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
//
		g_subSkinFrame = new CSkinMainWin();
		g_subSkinFrame->LoadSkin(ColorSkin::m_szSkinNeo);
		g_subSkinFrame->InstallSkin(hwnd);

	}

	return TRUE;
}

STDMETHODIMP ColorSkin::OnSkinXP()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	UpdateSkin(m_szSkinXP);
	
	return S_OK;
}

STDMETHODIMP ColorSkin::OnSkinNeostyle()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	UpdateSkin(m_szSkinNeo);
	return S_OK;
}

BOOL ColorSkin::UpdateSkin( CString szResPath )
{
	
	if(g_subSkinFrame!=NULL)
	{
		g_subSkinFrame->LoadSkin(szResPath);
		if(g_subSkinFrame->GetHwnd())
			SendMessage(g_subSkinFrame->GetHwnd(),WM_NCPAINT,0,0);
			
	}

	return TRUE;
}